using System;
using System.Collections.Generic;
using Com.ContentRendering.Api.DataEngine;
using ContentRenderingApi.Configuration;

namespace ContentRenderingApi.Data
{
    /// <summary/>
    internal class DefaultData : AbstractData
    {
        private IEnumerator<KeyValuePair<string, object>> _namedParameters;
        private IEnumerator<object> _parameters;

        /// <summary/>
        internal DefaultData(
            ReflectionCache reflectionCache,
            TransformationConfiguration transformationConfiguration,
            bool isCaching,
            IEnumerator<KeyValuePair<string, object>> namedParameters,
            IEnumerator<object> parameters)
            : base(
            reflectionCache,
            transformationConfiguration, 
            isCaching,
            null)            
        {
            this._namedParameters = namedParameters;
            this._parameters = parameters;
        }

        /// <summary/>
        protected override void ResolveChildData(List<object> values, string name)
        {
            // move the enumerator index to the start
            this._namedParameters.Reset();

            // check for matching parameters
            while (this._namedParameters.MoveNext())
            {
                // does the name match ... if not move on
                if (this._namedParameters.Current.Key != name)
                {
                    continue;
                }

                // if the value is null we treat it differently .... that is the data engine isn't used
                // this is because the parameter has been explicitly defined via the add atribute method
                // so treat the value as a null value and move on
                if (this._namedParameters.Current.Value == null)
                {
                    values.Add(null);

                    // process the next input
                    continue;
                }
                
                // find the child data of the current data for the given name
                IEnumerator<object> enumerator = SelfReflection.Translate(
                    base.ReflectionCache,
                    this._namedParameters.Current.Value);

                // move each element to the new list
                while (enumerator.MoveNext())
                {
                    values.Add(enumerator.Current);
                }
            }

            // move the enumerator index to the start
            this._parameters.Reset();

            // check for matching parameters
            while (this._parameters.MoveNext())
            {
                // expand the object
                IEnumerator<object> enumerator = SelfReflection.Translate(
                    base.ReflectionCache,
                    this._parameters.Current);

                while (enumerator.MoveNext())
                {
                    // find the child data of the current data for the given name
                    object newValue = ChildReflection.Translate(
                        base.ReflectionCache,
                        enumerator.Current,
                        name);

                    // expand the object
                    IEnumerator<object> newEnumerator = SelfReflection.Translate(
                        base.ReflectionCache,
                        newValue);

                    while (newEnumerator.MoveNext())
                    {
                        values.Add(newEnumerator.Current);
                    }
                }
            }
        }

        /// <summary/>
        protected override string Name
        {
            get { return null; }
        }

        /// <summary/>
        internal override object RawValue
        {
            get { return null; }
        }

        /// <summary/>
        internal override int Length
        {
            get { return Constant.DEFAULT_LENGTH; }
        }

        /// <summary/>
        internal override int Position
        {
            get { return Constant.DEFAULT_POSITION; }
        }

        /// <summary/>
        protected override void AssignPosition(int position)
        {
            // nothing to do
        }
    }
}
